package Servlet;

import bean.Answer;
import bean.Problem;
import bean.Question;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.org.apache.bcel.internal.classfile.Code;
import compile.CodeInValidException;
import compile.ProblemNotFoundException;
import compile.Task;
import dao.ProblemDao;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 张
 * Date: 2025-01-25
 * Time: 16:10
 */
@WebServlet("/compile")
public class CompileServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    private ProblemDao problemDao = new ProblemDao();
    //解析请求的内部类
    static class CompileRequest {
        public int id;
        public String code;
    }

    //解析响应的内部类
    static class CompileResponse {
        //约定 error为0表示编译运行正常,error为1编译出错,error为2表示运行出错(用户提交的代码有问题)
        //error为3表示其他错误
        public int error;
        public String reason;
        public String stdout;
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("用户当前的工作目录: " + System.getProperty("user.dir"));
        CompileResponse compileResponse = new CompileResponse();
        CompileRequest compileRequest = null;
        try {

            resp.setContentType("application/json;charset=utf8");
            // 1.读取正文,按照json格式进行解析
            String body = readBody(req);
            compileRequest = objectMapper.readValue(body, CompileRequest.class);
            // 2.根据id在数据库中查询到题目详情 => 得到测试用例代码
            Problem problem = problemDao.selectOne(compileRequest.id);
            if(problem == null) {
                //题目id不存在,抛出一个异常
                throw new ProblemNotFoundException();
            }

            //testCode 为测试用例的代码
            String testCode = problem.getTestCode();
            //requestCode 为用户提交的代码
            String requestCode = compileRequest.code;
            // 3.把用户提交的代码和测试用例代码,给拼接成一个完整的代码
            String finalCode = mergeCode(requestCode,testCode);
            if (finalCode == null) {
                throw new CodeInValidException();
            }
            System.out.println(3);
            System.out.println(finalCode);
            // 4.创建一个Task实例,调用类名的compileAndRun 来进行编译运行
            Task task = new Task();
            Question question = new Question();
            question.setCode(finalCode);
            Answer answer = task.compileAndRun(question);
            System.out.println("[CompileServlet] 编译执行的结果为 : " + answer.getStdout());
            // 5.根据Task运行的结果,包装成一个HTTP响应
            compileResponse.error = answer.getError();
            compileResponse.reason = answer.getReason();
            compileResponse.stdout = answer.getStdout();
        } catch (ProblemNotFoundException e) {
            // 处理题目没有找到的场景
            compileResponse.error = 3;
            compileResponse.reason = "没有找到指定的题目,id = " + compileRequest.id;

        } catch (CodeInValidException e) {
            compileResponse.error = 3;
            compileResponse.reason = "提交代码不符合要求";
        } finally {
            //转换成json字符串发回给浏览器
            String respString = objectMapper.writeValueAsString(compileResponse );
            resp.getWriter().write(respString);
        }

    }

    private static String readBody(HttpServletRequest req) throws UnsupportedEncodingException {
        // 1.先根据请求头里面的ContentLength获取body的长度(字节)
        int contentLength = req.getContentLength();
        // 2.按照这个长度准备好一个字节数组
        byte[] buffer = new byte[contentLength];
        // 3.通过req里面的getInputStream方法,获取到body的流对象
        try (InputStream inputStream = req.getInputStream()){
            // 4.基于流对象读取内容,然后把内容放到 byte[] 数组中即可
            inputStream.read(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 5.把byte[] 数组的内容构造成一个String
        return new String(buffer,"utf8");
    }

    private static String mergeCode(String requestCode, String testCode) {
        // 1.查找requestCode中的最后一个}
        int pos = requestCode.lastIndexOf("}");
        if(pos == -1) {
            //说明提交代码完全没有},是非法代码
            return null;
        }
        //2.进行截取
        String subStr = requestCode.substring(0,pos);
        //3.拼接
        return subStr + testCode + "}";
    }
}


